package com.threader.ui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
import java.util.Random;

import javax.swing.AbstractButton;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import org.apache.log4j.Logger;
import org.hibernate.HibernateException;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.classic.Session;

import com.threader.bo.Passport;
import com.threader.bo.People;
import com.threader.bo.Place;
import com.threader.bo.SomeObject;
import com.threader.bo.Time;
import com.threader.utils.Config;
import com.threader.utils.ConstantRegistry;

public class ThreadsManager extends JFrame implements Observer {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	private static Logger logger = Logger.getLogger(ThreadsManager.class);

	private JPanel controlPanel = null;
	private JPanel statusObjectsPanel = null;
	private JPanel statusPeoplesPanel = null;
	private JPanel statusPlacesPanel = null;
	
	private JLabel statusPeoplesLabel = new JLabel();
	private JLabel statusPlacesLabel = new JLabel();
	private JLabel statusObjectsLabel = new JLabel();
	private JLabel timeLabel = null;
	private JTable peoplesTable = null;
	private JTable objectsTable = null;
	private JTable placesTable = null;
	private SomeObjectsTableModel objectsTableModel = new SomeObjectsTableModel();
	private PeoplesTableModel peoplesTableModel = new PeoplesTableModel();
	private PlacesTableModel placesTableModel = new PlacesTableModel();
	private SomeObject selectedObject = null;
	private People selectedPeople = null;
	private Place selectedWorckPlace = null;
	private Time time = null;

	// 1000*60*60;

	public ThreadsManager(String string) {
		super(string);
		time = new Time(Time.SEC, new ActionListener() {
			public void actionPerformed(ActionEvent evt) {
				time.setCurrentDate();
				getTimeLabel();
			}
		});
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		addWindowListener(new WindowListener(){
			public void windowOpened(WindowEvent e) {
			}

			public void windowClosing(WindowEvent e) {
			}

			public void windowClosed(WindowEvent e) {
			}

			public void windowIconified(WindowEvent e) {
			}

			public void windowDeiconified(WindowEvent e) {
			}

			public void windowActivated(WindowEvent e) {
			}

			public void windowDeactivated(WindowEvent e) {
			}
			
		});
		setSize(600, 400);
		getContentPane().setLayout(new BorderLayout());
		getContentPane().add(getControlPanel(), BorderLayout.NORTH);
		getContentPane().add(getTabbedPanel(), BorderLayout.CENTER);
//		getContentPane().add(getStatusPanel(), BorderLayout.SOUTH);

		setVisible(true);

		Session session = getSession();
		List<Place> list = session.createQuery("from Place").list();
//		for(Place p: list){
//			placesTableModel.addPlace(p);
//		}
		placesTableModel.setPlasesList(list);
		placesTable.addRowSelectionInterval(0, 0);
		
		People p = new People(time,	new Passport("Ivan", "Durak", Passport.MAIL, new GregorianCalendar(1935, 12, 25)));
		peoplesTableModel.addPeople(p);
		list.get(1).isNeedPeople(p);

		People p1 = new People(time, new Passport("Bogdan", "Stupka", Passport.MAIL, new GregorianCalendar(1945, 1, 15)));
		peoplesTableModel.addPeople(p1);
		list.get(1).isNeedPeople(p1);

		People p2 = new People(time, new Passport("Anna", "Karenina", Passport.FEMAIL, new GregorianCalendar(1940, 11, 1)));
		peoplesTableModel.addPeople(p2);
		list.get(2).isNeedPeople(p2);

		People p3 = new People(time, new Passport("Britney", "Spears", Passport.FEMAIL, new GregorianCalendar(1940, 11, 1)));
		peoplesTableModel.addPeople(p3);

		People p4 = new People(time, new Passport("Elthon", "John", Passport.MAIL, new GregorianCalendar(1940, 11, 2)));
		peoplesTableModel.addPeople(p4);

		People p5 = new People(time, new Passport("Bruce", "Willis", Passport.MAIL, new GregorianCalendar(1946, 6, 20)));
		peoplesTableModel.addPeople(p5);

		People p6 = new People(time, new Passport("Silvester", "Stalonne", Passport.MAIL, new GregorianCalendar(1937, 9, 22)));
		peoplesTableModel.addPeople(p6);
		list.get(5).isNeedPeople(p6);

		People p7 = new People(time, new Passport("Avril", "Lavigne", Passport.FEMAIL, new GregorianCalendar(1937, 10, 12)));
		peoplesTableModel.addPeople(p7);
		list.get(5).isNeedPeople(p7);

		peoplesTable.addRowSelectionInterval(0, 0);

		
//		objectsTableModel.addObject(new SomeObject("Laptop"));
//		objectsTableModel.addObject(new SomeObject("Mobile Phone"));
//		objectsTableModel.addObject(new SomeObject("Car"));
		
		statusPeoplesLabel.setText("Peoples count: "
				+ peoplesTableModel.peoplesList.size());

		statusPlacesLabel.setText("Places count: "
				+ placesTableModel.getRowCount());

		statusObjectsLabel.setText("Objects count: "
				+ objectsTableModel.ObjectsList.size());
		
	}

	public static void main(String[] args) {
		// first check if the command line is trying to override the default property file path
		String defaultPropertiesPath = System.getProperty("config.default.filepath");
		if (defaultPropertiesPath == null) {
			// get path to default initialization properties file using our context
			defaultPropertiesPath = "defaultProperties";
			System.setProperty("config.default.filepath", defaultPropertiesPath);
		}
		try {
			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
		} catch (UnsupportedLookAndFeelException e) {
		} catch (ClassNotFoundException e) {
		} catch (InstantiationException e) {
		} catch (IllegalAccessException e) {
		}
		new ThreadsManager(Config.getProperty("APPNAME"));
	}

	// public void setStartThread(JButton startThread) {
	// this.startThread = startThread;
	// }
	//
	// public JButton getStartThread() {
	// if(startThread==null){
	// startThread = new JButton("Start");
	// startThread.addActionListener(new ActionListener(){
	// public void actionPerformed(ActionEvent arg0) {
	// selectedThread.start();
	// }
	// });
	// }
	// return startThread;
	// }
	//
	// public void setStopThread(JButton stopThread) {
	// this.stopThread = stopThread;
	// }
	//
	// public JButton getStopThread() {
	// if(stopThread == null){
	// stopThread = new JButton("Stop");
	// stopThread.addActionListener(new ActionListener(){
	// public void actionPerformed(ActionEvent arg0) {
	// selectedThread.stop();
	// }
	// });
	// }
	// return stopThread;
	// }

//	public void setManagerThread(JButton managerThread) {
//		this.peopleInformer = managerThread;
//	}

//	public void setThreadsTable(JTable threadsList) {
//		this.peoplesTable = threadsList;
//	}

	public JTable getObjectsTable() {
		if (objectsTable == null) {
			objectsTable = new JTable(objectsTableModel);
			objectsTable.getSelectionModel().addListSelectionListener(
					new ListSelectionListener() {
						public void valueChanged(ListSelectionEvent e) {
							worckPlacesTableSelectionChanged();
						}
					});
			objectsTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		}
		return objectsTable;
	}

//	private void objectsTableSelectionChanged() {
//		if (selectedObject != null)
//			selectedObject.deleteObserver(ThreadsManager.this);
//		
//		if (objectsTable.getSelectedRow() > -1) {
//			selectedObject = objectsTableModel.getObject(objectsTable.getSelectedRow());
//			selectedObject.addObserver(ThreadsManager.this);
//		}
//	}

	public JTable getWorckPlacesTable() {
		if (placesTable == null) {
			placesTable = new JTable(placesTableModel);
			placesTable.getSelectionModel().addListSelectionListener(
					new ListSelectionListener() {
						public void valueChanged(ListSelectionEvent e) {
							worckPlacesTableSelectionChanged();
						}
					});
			placesTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		}
		return placesTable;
	}
	
	private void worckPlacesTableSelectionChanged() {
		if (selectedWorckPlace != null)
			selectedWorckPlace.deleteObserver(ThreadsManager.this);
		
		if (placesTable.getSelectedRow() > -1) {
			selectedWorckPlace = placesTableModel.getPlace(placesTable.getSelectedRow());
			selectedWorckPlace.addObserver(ThreadsManager.this);
		}
	}

	public JTable getPeoplesTable() {
		if (peoplesTable == null) {
			peoplesTable = new JTable(peoplesTableModel);
			peoplesTable.getSelectionModel().addListSelectionListener(
					new ListSelectionListener() {
						public void valueChanged(ListSelectionEvent e) {
							peoplesTableSelectionChanged();
						}
					});
			peoplesTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		}
		return peoplesTable;
	}

	private void peoplesTableSelectionChanged() {
		if (selectedPeople != null)
			selectedPeople.deleteObserver(ThreadsManager.this);
		
		if (peoplesTable.getSelectedRow() > -1) {
			selectedPeople = peoplesTableModel.getPeople(peoplesTable.getSelectedRow());
			selectedPeople.addObserver(ThreadsManager.this);
		}
	}

	public JTabbedPane getTabbedPanel(){
		JTabbedPane tabbedPane = new JTabbedPane();

		JPanel peoplesPanel = new JPanel();
		peoplesPanel.setLayout(new BorderLayout());

		JPanel controlPeoplesBtns = new JPanel(new FlowLayout(FlowLayout.LEFT));
		JButton createPeopleBtn = new JButton("New");
		createPeopleBtn.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				int sex = new Random().nextInt(99)+1; 
				peoplesTableModel.addPeople(new People(time,
						new Passport(
							(sex>50)?ConstantRegistry.firstNamesF[new Random().nextInt(ConstantRegistry.firstNamesF.length-1)+1]:
								ConstantRegistry.firstNamesM[new Random().nextInt(ConstantRegistry.firstNamesF.length-1)+1],
							String.valueOf(System.currentTimeMillis()),
							(sex>50)?1:0,
							new GregorianCalendar(new Random().nextInt(30)+1970-17-30, new Random().nextInt(11)+1, new Random().nextInt(25)+1)
						)));
				statusPeoplesLabel.setText("Peoples count: "
						+ peoplesTableModel.peoplesList.size());
				int selRow = peoplesTableModel.getRowCount() - 1;
				peoplesTable.addRowSelectionInterval(0, selRow);
			}
		});

		controlPeoplesBtns.add(createPeopleBtn);
		JButton destroyThread = new JButton("Delete");
		destroyThread.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				int selRow = peoplesTable.getSelectedRow();
				if (selRow > -1) {
					People people = peoplesTableModel.getPeople(selRow);
					people.kill();
					peoplesTableModel.delPeople(selRow);

					statusPeoplesLabel.setText("Peoples count: "+ peoplesTableModel.peoplesList.size());
					if(selRow > peoplesTableModel.getRowCount() - 1)
						selRow = peoplesTableModel.getRowCount() - 1;
					if(selRow>=0)
						peoplesTable.addRowSelectionInterval(0, selRow);
				}
			}
		});

		controlPeoplesBtns.add(destroyThread);

		JButton peopleInformer = new JButton("Info");
		peopleInformer.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				if (peoplesTable.getSelectedRow() > -1) {
					selectedPeople.showPassport();
				}
			}
		});
		
		controlPeoplesBtns.add(peopleInformer);
		peoplesPanel.add(controlPeoplesBtns, BorderLayout.NORTH);
		
		JScrollPane peoplesTable = new JScrollPane(getPeoplesTable());
		peoplesPanel.add(peoplesTable,BorderLayout.CENTER);
		peoplesPanel.add(getPeoplesStatusPanel(),BorderLayout.SOUTH);
		
		tabbedPane.addTab("Peoples", peoplesPanel);

		JPanel worckplacesPanel = new JPanel();
		worckplacesPanel.setLayout(new BorderLayout());

		JPanel controlPlacesBtns = new JPanel(new FlowLayout(FlowLayout.LEFT));
		JButton createPlaceBtn = new JButton("New");
		createPlaceBtn.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				Place p = new Place().setName(new Random().nextInt(99)+" "+new Random().nextInt(99)).setTime(time);
				placesTableModel.addPlace(p);
				
				try{
					Session session = getSession();
					session.getTransaction().begin();
					session.saveOrUpdate(p);
					session.getTransaction().commit();
				} catch (HibernateException e) {
					e.printStackTrace();
				}
				catch (Exception e) {
					System.err.println("Creation failed. " + e.getMessage());
				}
				
				statusPlacesLabel.setText("Places count: "
						+ placesTableModel.getRowCount());

				int selRow = placesTableModel.getRowCount() - 1;
				placesTable.addRowSelectionInterval(0, selRow);
			}
		});

		controlPlacesBtns.add(createPlaceBtn);

		JButton destroyPlaceBtn = new JButton("Delete");
		destroyPlaceBtn.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				int selRow = placesTable.getSelectedRow();
				if(selRow > -1){
					Session session = getSession();
					Place p = placesTableModel.getPlace(selRow);
					session.getTransaction().begin();
					session.delete(p);
					session.getTransaction().commit();
					placesTableModel.delPlace(selRow);
					statusPlacesLabel.setText("Places count: "
							+ placesTableModel.getRowCount());
					if(selRow > placesTableModel.getRowCount() - 1)
						selRow = placesTableModel.getRowCount() - 1;
					placesTable.addRowSelectionInterval(0, selRow);
				}
			}
		});
		
		controlPlacesBtns.add(destroyPlaceBtn);
		JButton worckPlaceInformerBtn = new JButton("Info");
		worckPlaceInformerBtn.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
			}
		});

		controlPlacesBtns.add(worckPlaceInformerBtn);
		worckplacesPanel.add(controlPlacesBtns, BorderLayout.NORTH);
		
		JScrollPane worckplacesTable = new JScrollPane(getWorckPlacesTable());
		worckplacesPanel.add(worckplacesTable,BorderLayout.CENTER);
		worckplacesPanel.add(getPlacesStatusPanel(),BorderLayout.SOUTH);

		tabbedPane.addTab("Places", worckplacesPanel);

		
		JPanel objectsPanel = new JPanel();
		objectsPanel.setLayout(new BorderLayout());

		JPanel controlObjectsBtns = new JPanel(new FlowLayout(FlowLayout.LEFT));
		JButton createObjectBtn = new JButton("New Object");

		controlObjectsBtns.add(createObjectBtn);

		JButton destroyObjectBtn = new JButton("Delete Object");
		
		controlObjectsBtns.add(destroyObjectBtn);
		JButton ObjectInformerBtn = new JButton("Object Information");
		ObjectInformerBtn.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
			}
		});

		controlObjectsBtns.add(ObjectInformerBtn);
		objectsPanel.add(controlObjectsBtns, BorderLayout.NORTH);
		
		JScrollPane objectsTable = new JScrollPane(getObjectsTable());
		objectsPanel.add(objectsTable,BorderLayout.CENTER);
		objectsPanel.add(getObjectsStatusPanel(),BorderLayout.SOUTH);

		tabbedPane.addTab("Objects", objectsPanel);
		
		
		return tabbedPane;
		
	}
	
//	public void setControlPanel(JPanel controlPanel) {
//		this.controlPanel = controlPanel;
//	}

	public JPanel getControlPanel() {
		if (controlPanel == null) {
			controlPanel = new JPanel();
			controlPanel.setLayout(new BoxLayout(controlPanel, BoxLayout.Y_AXIS));
			JPanel mainPanel = new JPanel();
			mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));

			JPanel speedButtonsPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
			JButton x1Btn = new JButton("x1");
			JButton x2Btn = new JButton("x2");
			JButton x3Btn = new JButton("x3");
			JButton x4Btn = new JButton("x4");
			JButton x5Btn = new JButton("x5");
			JButton x10Btn = new JButton("x10");
			JButton x100Btn = new JButton("x100");
			JButton pauseBtn = new JButton("Pause");
			JButton playBtn = new JButton("Play");
			final JLabel speedLabel = new JLabel("Now Speed x1");
			speedButtonsPanel.add(x1Btn);
			speedButtonsPanel.add(x2Btn);
//			speedButtonsPanel.add(x3Btn);
//			speedButtonsPanel.add(x4Btn);
			speedButtonsPanel.add(x5Btn);
			speedButtonsPanel.add(x10Btn);
//			speedButtonsPanel.add(x100Btn);
			speedButtonsPanel.add(pauseBtn);
			speedButtonsPanel.add(playBtn);
			speedButtonsPanel.add(speedLabel);

//			JPanel currentTimePanel = new JPanel();
//			currentTimePanel.add(getTimeLabel());
			speedButtonsPanel.add(getTimeLabel());
			mainPanel.add(speedButtonsPanel);
//			mainPanel.add(currentTimePanel);
			
			controlPanel.add(mainPanel);

			ActionListener speedBtnsListener = new ActionListener() {
				public void actionPerformed(ActionEvent arg0) {
					String s = ((AbstractButton) arg0.getSource()).getText();
					time.setDelay(Time.SEC/ new Integer(s.substring(1, s.length())));
					speedLabel.setText("Now Speed " + s);
				}
			};
			x1Btn.addActionListener(speedBtnsListener);
			x2Btn.addActionListener(speedBtnsListener);
			x3Btn.addActionListener(speedBtnsListener);
			x4Btn.addActionListener(speedBtnsListener);
			x5Btn.addActionListener(speedBtnsListener);
			x10Btn.addActionListener(speedBtnsListener);
			x100Btn.addActionListener(speedBtnsListener);

			pauseBtn.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent arg0) {
					time.stop();
				}
			});

			playBtn.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent arg0) {
					time.start();
				}
			});

		}
		return controlPanel;
	}

//	public void setStatusPanel(JPanel statusPanel) {
//		this.statusPanel = statusPanel;
//	}

	public JPanel getObjectsStatusPanel() {
		if (statusObjectsPanel == null) {
			statusObjectsPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
			statusObjectsPanel.add(statusObjectsLabel);
			statusObjectsLabel.setText("Objects count: "
					+ objectsTableModel.ObjectsList.size());
		}
		return statusObjectsPanel;
	}
	
	public JPanel getPeoplesStatusPanel() {
		if (statusPeoplesPanel == null) {
			statusPeoplesPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
			statusPeoplesPanel.add(statusPeoplesLabel);
			statusPeoplesLabel.setText("Peoples count: "
					+ peoplesTableModel.peoplesList.size());
		}
		return statusPeoplesPanel;
	}

	public JPanel getPlacesStatusPanel() {
		if (statusPlacesPanel == null) {
			statusPlacesPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
			statusPlacesPanel.add(statusPlacesLabel);
			statusPlacesLabel.setText("Places count: "
					+ placesTableModel.getRowCount());
		}
		return statusPlacesPanel;
	}

	
//	public void setDestroyThread(JButton destroyThread) {
//		this.destroyThread = destroyThread;
//	}

//	public void setTimeLabel(JLabel timeLabel) {
//		this.timeLabel = timeLabel;
//	}

	public JLabel getTimeLabel() {
		if (timeLabel == null) {
			timeLabel = new JLabel();
			timeLabel.setForeground(Color.black);
			timeLabel.setBorder(
					BorderFactory.createCompoundBorder(BorderFactory
							.createLineBorder(Color.black), BorderFactory
							.createEmptyBorder(5, 5, 5, 5)));
		}
		timeLabel.setText("<html><center>" + time.getDay() + " "
				+ time.getMonth() + " " + time.getYear() + ", <b>" + "("
				+ time.getWeek() + ") " + time.getHour() + ":"
				+ time.getMinute() + "</b></center></html>");

		return timeLabel;
	}

	public void update(Observable o, Object arg) {
	}
	
	public Session getSession(){
		SessionFactory sessionFactory;
		try {
			sessionFactory = new Configuration().configure("hibernate.cfg.xml").buildSessionFactory();
			return sessionFactory.openSession();
		}
		catch (Throwable ex) {
			System.err.println("Initial SessionFactory creation failed. " + ex.getLocalizedMessage());
			throw new ExceptionInInitializerError(ex);
		}
	}
}
